<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>TLS - Rauthy Documentation</title>


        <!-- Custom HTML head -->

        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="../favicon.svg">
        <link rel="shortcut icon" href="../favicon.png">
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        <link rel="stylesheet" href="../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" id="highlight-css" href="../highlight.css">
        <link rel="stylesheet" id="tomorrow-night-css" href="../tomorrow-night.css">
        <link rel="stylesheet" id="ayu-highlight-css" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        <link rel="stylesheet" href=".././mdbook-admonish.css">


        <!-- Provide site root and default themes to javascript -->
        <script>
            const path_to_root = "../";
            const default_light_theme = "light";
            const default_dark_theme = "navy";
        </script>
        <!-- Start loading toc.js asap -->
        <script src="../toc.js"></script>
    </head>
    <body>
    <div id="mdbook-help-container">
        <div id="mdbook-help-popup">
            <h2 class="mdbook-help-title">Keyboard shortcuts</h2>
            <div>
                <p>Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters</p>
                <p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
                <p>Press <kbd>?</kbd> to show this help</p>
                <p>Press <kbd>Esc</kbd> to hide this help</p>
            </div>
        </div>
    </div>
    <div id="body-container">
        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                let theme = localStorage.getItem('mdbook-theme');
                let sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
            let theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            const html = document.documentElement;
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add("js");
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            let sidebar = null;
            const sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <!-- populated by js -->
            <mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
            <noscript>
                <iframe class="sidebar-iframe-outer" src="../toc.html"></iframe>
            </noscript>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle">
                <div class="sidebar-resize-indicator"></div>
            </div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="default_theme">Auto</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">Rauthy Documentation</h1>

                    <div class="right-buttons">
                        <a href="../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="tls"><a class="header" href="#tls">TLS</a></h1>
<p>If you do have TLS certificates from another source already, skip directly to <a href="#config">Config</a>.</p>
<h2 id="generating-certificates"><a class="header" href="#generating-certificates">Generating Certificates</a></h2>
<p>You can either generate TLS certificates yourself and manage your own CA, or (for testing purposes) let Rauthy generate
self-signed certificates. Rauthys self-signed ones should only be used for testing, but they are generated somewhat
securely. Rauthy will create it's own CA and save it do the database, with the private key being encrypted with the
configured <code>encryption.key_active</code>. The CA will be valid for 10 years and re-used for signing the server certs in all
instances, even you do an HA deployment.</p>
<div id="admonition-caution" class="admonition admonish-warning" role="note" aria-labelledby="admonition-caution-title">
<div class="admonition-title">
<div id="admonition-caution-title">
<p>Caution</p>
</div>
<a class="admonition-anchor-link" href="#admonition-caution"></a>
</div>
<div>
<p>Some browsers like Firefox do not allow the registration of Passkeys when using self-signed TLS certificates. To be able
to do this during testing, you would need to add the generated CA certificate to your trust store.</p>
<p>In such a case, you will probably see an error like <code>Invalid Key</code> during registration. This happens in insecure contexts.</p>
</div>
</div>
<h3 id="automatic-self-signed-certificates"><a class="header" href="#automatic-self-signed-certificates">Automatic self-signed certificates</a></h3>
<p>Generating self-signed TLS certificates for the Rauthy HTTPS server is pretty straight forward. Keep in mind, that these
will only be generated for the HTTPS server and NOT for hiqlite internal cluster traffic, if you have an HA deployment.</p>
<p>To generate TLS certificates on startup, you only need to set <code>tls.generate_self_signed = true</code>:</p>
<pre><code class="language-toml">[tls]
# If set to `true`, Rauthy will generate self-signed TLS certs and copy
# them into `tls/self_signed_cert.pem` and `tls/self_signed_key.pem`.
# It will also IGNORE any `cert_path` / `key_path`.
#
# CAUTION: If set to `true`, it will delete existing files:
# - `tls/self_signed_cert.pem`
# - `tls/self_signed_key.pem`
#
# This should only be used for testing and never in production!
#
# default: false
# overwritten by: TLS_GENERATE_SELF_SIGNED
generate_self_signed = true
</code></pre>
<p>If you only care about testing certificates for the HTTPS server, you don't need to configure anything else at this
point.</p>
<h3 id="manually-managed-certificates"><a class="header" href="#manually-managed-certificates">Manually managed certificates</a></h3>
<div id="admonition-note" class="admonition admonish-note" role="note" aria-labelledby="admonition-note-title">
<div class="admonition-title">
<div id="admonition-note-title">
<p>Note</p>
</div>
<a class="admonition-anchor-link" href="#admonition-note"></a>
</div>
<div>
<p>We are using another project of mine called <a href="https://github.com/sebadob/nioca">Nioca</a> for an easy creation of a
fully functioning and production ready private Root Certificate Authority (CA).</p>
</div>
</div>
<p>I suggest to use <code>docker</code> for this task. Otherwise, you can use the <code>nioca</code> binary directly on any linux machine.
If you want a permanent way of generating certificates for yourself, take a look at Rauthys <code>justfile</code> and copy
and adjust the recipes <code>create-root-ca</code> and <code>create-end-entity-tls</code> to your liking.<br />
If you just want to get everything started quickly, follow these steps:</p>
<h4 id="create-an-alias-for-the-docker-command"><a class="header" href="#create-an-alias-for-the-docker-command">Create an alias for the <code>docker</code> command</a></h4>
<pre><code>alias nioca='docker run --rm -it -v ./:/ca -u $(id -u ${USER}):$(id -g ${USER}) ghcr.io/sebadob/nioca'
</code></pre>
<p>To see the full feature set for more customization than mentioned below:</p>
<pre><code>nioca x509 -h
</code></pre>
<h4 id="generate-full-certificate-chain"><a class="header" href="#generate-full-certificate-chain">Generate full certificate chain</a></h4>
<p>To make your browser happy, your need to have at least one <code>--alt-name-dns</code> for the URL of your application.
You can define as many of them as you like.</p>
<pre><code>nioca x509 \
    --cn 'Rauthy Default' \
    --o 'Rauthy OIDC' \
    --alt-name-dns localhost \
    --alt-name-dns rauthy.rauthy \
    --alt-name-dns rauthy.rauthy.svc.cluster.local \
    --usages-ext server-auth \
    --usages-ext client-auth \
    --stage full \
    --clean
</code></pre>
<p>You will be asked 6 times (yes, 6) for an at least 16 character password:</p>
<ul>
<li>The first 3 times, you need to provide the encryption password for your Root CA</li>
<li>The last 3 times, you should provide a different password for your Intermediate CA</li>
</ul>
<p>When everything was successful, you will have a new folder named <code>x509</code> with sub folders <code>root</code>, <code>intermediate</code>
and <code>end_entity</code> in your current one.</p>
<p>From these, you will need the following files:</p>
<pre><code>cp x509/intermediate/ca-chain.pem . &amp;&amp; \
cp x509/end_entity/$(cat x509/end_entity/serial)/cert-chain.pem . &amp;&amp; \
cp x509/end_entity/$(cat x509/end_entity/serial)/key.pem .
</code></pre>
<ul>
<li>You should have 3 files in <code>ls -l</code>:</li>
</ul>
<pre><code>ca-chain.pem
cert-chain.pem
key.pem
</code></pre>
<h2 id="config"><a class="header" href="#config">Config</a></h2>
<p>The <a href="../config/config.html">reference config</a> contains a <code>TLS</code> section with all the values you can set.</p>
<p>For this example, we will be using the same certificates for both the internal cache mTLS connections and the
public facing HTTPS server.</p>
<h3 id="hiqlite"><a class="header" href="#hiqlite">Hiqlite</a></h3>
<p>Hiqlite can run the whole database layer, and it will always take care of caching. It can be configured to use TLS
internally, if you provide certificates. Simply provide the following values from the <code>TLS</code> section in the reference
config:</p>
<pre><code class="language-toml">[cluster]
# If given, these keys / certificates will be used to establish
# TLS connections between nodes.
#
# values are optional, overwritten by: HQL_TLS_{RAFT|API}_{KEY|CERT}
# overwritten by: HQL_TLS_RAFT_KEY
tls_raft_key = "tls/tls.key"
# overwritten by: HQL_TLS_RAFT_CERT
tls_raft_cert = "tls/tls.crt"
#tls_raft_danger_tls_no_verify = true

# overwritten by: HQL_TLS_API_KEY
tls_api_key = "tls/tls.key"
# overwritten by: HQL_TLS_RAFT_KEY
tls_api_cert = "tls/tls.crt"
#tls_api_danger_tls_no_verify = true
</code></pre>
<p>There is no problem using the same certificates for both networks, but you can optionally even separate them if you need
to. You could even re-use the Server TLS, if your DNS setup allows for this.</p>
<div id="admonition-note-1" class="admonition admonish-note" role="note" aria-labelledby="admonition-note-1-title">
<div class="admonition-title">
<div id="admonition-note-1-title">
<p>Note</p>
</div>
<a class="admonition-anchor-link" href="#admonition-note-1"></a>
</div>
<div>
<p>At the time of writing, it does not accept a custom Root CA yet. In this case you have to set the
<code>*_danger_tls_no_verify</code> to <code>true</code></p>
</div>
</div>
<h3 id="rauthy-server--api"><a class="header" href="#rauthy-server--api">Rauthy Server / API</a></h3>
<p>By default, rauthy will expect a certificate and a key file in <code>/app/tls/tls.key</code> and <code>/app/tls/tls.crt</code>, which
is the default naming for a Kubernetes TLS secret. The expected format is PEM, but you could provide the key in DER
format too, if you rename the file-ending to <code>*.der</code>.</p>
<pre><code class="language-toml">[tls]
## UI + API TLS

# Overwrite the path to the TLS certificate file in PEM
# format for rauthy
#
#default: 'tls/tls.crt'
# overwritten by: TLS_CERT
cert_path = 'tls/cert-chain.pem'

# Overwrite the path to the TLS private key file in PEM
# format for rauthy. If the path / filename ends with '.der',
# rauthy will parse it as DER, otherwise as PEM.
#
# default: 'tls/tls.key'
# overwritten by: TLS_KEY
key_path = 'tls/key.pem'
</code></pre>
<h3 id="kubernetes"><a class="header" href="#kubernetes">Kubernetes</a></h3>
<p>If you did not follow the above procedure to generate the CA and certificates, you may need to rename the files in the
following command, to create the Kubernetes secrets.</p>
<p><strong>Secrets - Rauthy Server / API</strong></p>
<pre><code>kubectl -n rauthy create secret tls rauthy-tls --key="key.pem" --cert="cert-chain.pem"
</code></pre>
<p><strong>Secrets - <code>hiqlite</code> cache</strong></p>
<pre><code>kubectl -n rauthy create secret tls hiqlite-tls --key="key.pem" --cert="cert-chain.pem"
</code></pre>
<div id="admonition-note-2" class="admonition admonish-note" role="note" aria-labelledby="admonition-note-2-title">
<div class="admonition-title">
<div id="admonition-note-2-title">
<p>Note</p>
</div>
<a class="admonition-anchor-link" href="#admonition-note-2"></a>
</div>
<div>
<p>We create the <code>hiqlite-tls</code> here with the exact same values. You could of course either use different certificates, or
not create a separate secret at all and just re-use the Rauthy TLS certificates, if you DNS setup allows for proper
validation in this case.</p>
</div>
</div>
<h4 id="config-adjustments---rest-api"><a class="header" href="#config-adjustments---rest-api">Config Adjustments - REST API</a></h4>
<p>We need to configure the newly created Kubernetes secrets in the <code>sts.yaml</code> from the
<a href="../getting_started/k8s.html#create-and-apply-the-stateful-set">Kubernetes</a> setup.</p>
<ol>
<li>In the <code>spec.template.spec.volumes</code> section, we need to mount the volumes from secrets:</li>
</ol>
<p><strong>REST API</strong>:</p>
<pre><code class="language-yaml">- name: rauthy-tls
  secret:
    secretName: rauthy-tls
</code></pre>
<p><strong><code>hiqlite</code> cache</strong>:</p>
<pre><code class="language-yaml">- name: hiqlite-tls
  secret:
    secretName: hiqlite-tls
</code></pre>
<ol start="2">
<li>In the <code>spec.template.spec.containers.[rauthy].volumeMounts</code> section, add::</li>
</ol>
<p><strong>REST API</strong>:</p>
<pre><code class="language-yaml">- mountPath: /app/tls/
  name: rauthy-tls
  readOnly: true
</code></pre>
<p><strong><code>hiqlite</code> cache</strong>:</p>
<pre><code class="language-yaml">- mountPath: /app/tls/hiqlite/
  name: hiqlite-tls
  readOnly: true
</code></pre>
<p>After having modified the config from above and the <code>sts.yaml</code> now, just apply both:</p>
<pre><code>kubectl apply -f config.yaml
kubectl apply -f sts.yaml
</code></pre>
<p>The <code>rauthy</code> pods should restart now and TLS is configured.</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../config/backup.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next prefetch" href="../config/sessions.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../config/backup.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next prefetch" href="../config/sessions.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="../elasticlunr.min.js"></script>
        <script src="../mark.min.js"></script>
        <script src="../searcher.js"></script>

        <script src="../clipboard.min.js"></script>
        <script src="../highlight.js"></script>
        <script src="../book.js"></script>

        <!-- Custom JS scripts -->


    </div>
    </body>
</html>
